#include "Headers/client.h"
#include "ui_client.h"

client::client(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::client)
{
    ui->setupUi(this);
    ChatBotInit();
    setWindowTitle("未知用户");
    MyEmijo = new Emijo();
    capture = new cv::VideoCapture();
    MessagesTcpPort=1112;
    MessagesTcpSocket = new QTcpSocket();
    setVidoTcpPort=1114;
    setVidoTcpSocket = new QTcpSocket();
    getVidoTcpPort=1115;
    getVidoTcpSocket = new QTcpSocket();
    vido = new Vido();
}

void client::ChatBotInit(){
    groupId = "1810541336101667371";
    apiKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiLlkajlpKfkvJ8iLCJVc2VyTmFtZSI6IuWRqOWkp-S8nyIsIkFjY291bnQiOiIiLCJTdWJqZWN0SUQiOiIxODEwNTQxMzM2MTEwMDU1OTc5IiwiUGhvbmUiOiIxNTMzMzQzNzIwNCIsIkdyb3VwSUQiOiIxODEwNTQxMzM2MTAxNjY3MzcxIiwiUGFnZU5hbWUiOiIiLCJNYWlsIjoiIiwiQ3JlYXRlVGltZSI6IjIwMjQtMDgtMDEgMjE6MDc6NDIiLCJpc3MiOiJtaW5pbWF4In0.VbEugvYEii4W70zg8dBrFhnd9o9WPUSVD4v5W5zSRnNsG7VqztHwwe9gR-CUo5u8OySTWNZkq1iUADL2l0P0HVl7pi3mrXD29m_KhTXlYmoWDG6MNENZAP4pHGX_F6pf-cditImuZipsbv1SDkXjyMKBP6JHUZt3tzjsxw3wGTWMXp0XJwPhzNFBRAMU9H0QGONtToW0HI3oqUcep3FUua3adUVEi5FnWFRuLncG9WWltJF_538p2cNzM8iYq8IJYGTI2nM8DrJZq0mX9XLJQ6_MUay9H475CqB2TjlL7FycAQM44dXGvYWfFXaHaP-cnh5x1kZ9HrV0TrUIK4SbmQ"; // 请替换为您的 API 密钥
    chatbot = new ChatBOT(groupId, apiKey);
    QObject::connect(chatbot,&ChatBOT::ResultOk,[&](){
        QString Messages = chatbot->htmlText;
        QString newMessages = chatbot->newhtml;
        QString time = QString::number(QDateTime::currentDateTime().toTime_t()); //时间戳
        QNChatMessage* messageW = new QNChatMessage(ui->listWidget->parentWidget());
        QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
        dealMessage(messageW, item, Messages,newMessages, time, QNChatMessage::User_She);
        ui->pushButton_7->setEnabled(true);
        ui->pushButton_7->setStyleSheet("background-color: rgb(51, 209, 122);");
    });
}

void client::closeEvent(QCloseEvent *event){
    Q_UNUSED(event);
    close();
}

client::~client()
{
    delete ui;
}

void client::MessagesSockerInit(){
    MessagesTcpSocket->connectToHost(ServerIp,MessagesTcpPort);
    connect(MessagesTcpSocket, &QTcpSocket::connected, this, [=](){
        QByteArray data=(QString(R"({
                                 "Type":%1,
                                 "User":"%2"
                                 })").arg(JOIN_TYPE).arg(UserName)).toUtf8();
        MessagesTcpSocket->write(data);
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setWindowTitle("成功");
        msgBox.setText("连接服务器成功！");
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.exec();
    });
    connect(MessagesTcpSocket, &QTcpSocket::readyRead, this, [=](){
        QString data = MessagesTcpSocket->readAll();
        QJsonDocument jsonDocument = QJsonDocument::fromJson(data.toUtf8());
        QVariant variant = jsonDocument.toVariant();
        QMap<QString, QVariant> map = variant.toMap();
        QString messages=map["Messages"].toString();
        QString time = QString::number(QDateTime::currentDateTime().toTime_t()); //时间戳
        QNChatMessage* messageW = new QNChatMessage(ui->listWidget->parentWidget());
        QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
        dealMessage(messageW, item, messages,messages , time, QNChatMessage::User_She);
        messageW->setTextSuccess();
    });
    if(!MessagesTcpSocket->waitForConnected(2*1000)) {
        setWindowTitle("未知用户");
        QMessageBox messageBox;
        messageBox.setIcon(QMessageBox::Critical);
        messageBox.setWindowTitle("错误");
        messageBox.setText("服务连接错误，请检查服务器是否正确！");
        messageBox.setStandardButtons(QMessageBox::Ok);
        messageBox.exec();
    }
}

void client::setVidoInit(){
    setVidoTcpSocket->connectToHost(ServerIp,setVidoTcpPort);
    connect(setVidoTcpSocket, &QTcpSocket::connected, this, [=](){
        QByteArray data=(QString(R"({
                                 "Type":%1,
                                 "User":"%2"
                                 })").arg(JOIN_TYPE).arg(UserName)).toUtf8();
        setVidoTcpSocket->write(data);
    });
    connect(setVidoTcpSocket,&QTcpSocket::readyRead,this,[=](){
        QString data = setVidoTcpSocket->readAll();
        QJsonDocument jsonDocument = QJsonDocument::fromJson(data.toUtf8());
        QVariant variant = jsonDocument.toVariant();
        QMap<QString, QVariant> map = variant.toMap();
        int Type = map["Type"].toInt();
        QString User = map["User"].toString();
        QString Sender = map["Sender"].toString();
        if(Type==VOID_OK_TYPE){
            VidoData();
        }else if(Type==VOID_NO_TYPE){
            QMessageBox::information(this, "提醒", "用户拒绝通话！",
                                         QMessageBox::Ok);
        }
        else{
            QMessageBox::StandardButton reply;
            reply = QMessageBox::question(this, "来电", tr("是否接听%1的来电？").arg(Sender),
                                          QMessageBox::Yes | QMessageBox::No);
            if (reply == QMessageBox::Yes) {
                QByteArray data=(QString(R"({
                                         "Type":%1,
                                         "User":"%2"
                                         })").arg(VOID_OK_TYPE).arg(Sender)).toUtf8();
                setVidoTcpSocket->write(data);
                if(!setVidoTcpSocket->waitForBytesWritten(10*1000)) {
                    qDebug()<<(QString("网络请求超时,原因：%1").arg(setVidoTcpSocket->errorString()));
                    return;
                }
//                VidoData();
                ui->pushButton_4->setText("关闭");
                vido->show();
            } else {
                QByteArray data=(QString(R"({
                                         "Type":%1,
                                         "User":"%2"
                                         })").arg(VOID_NO_TYPE).arg(Sender)).toUtf8();
                setVidoTcpSocket->write(data);
            }
        }
    });
    if(!setVidoTcpSocket->waitForConnected(2*1000)) {
        qDebug()<<"error!";
        return;
    }
}
void client::getVidoInit(){
    getVidoTcpSocket->connectToHost(ServerIp,getVidoTcpPort);
    connect(getVidoTcpSocket, &QTcpSocket::connected, this, [=](){
        QByteArray data=(QString(R"({
                                 "Type":%1,
                                 "User":"%2"
                                 })").arg(JOIN_TYPE).arg(UserName)).toUtf8();
        getVidoTcpSocket->write(data);
    });
    connect(getVidoTcpSocket, &QTcpSocket::readyRead, this, [=](){
        QByteArray data = getVidoTcpSocket->readAll();
        if(data=="Commopasd"){
            vido->MEclear();
            vido->SHEclear();
            ui->pushButton_4->setText("视频通话");
            if(capture->isOpened()){
                capture->release();
            }
            vido->hide();
            return;
        }else if(data=="")return ;
        QImage image;
        image.loadFromData(data, "JPEG");
        QPixmap receivedPixmap;
        receivedPixmap = QPixmap::fromImage(image.rgbSwapped());
        vido->setSHEPixmap(receivedPixmap);
    });
}

/*气泡式聊天框*/
void client::dealMessage(QNChatMessage *messageW, QListWidgetItem *item, QString text,QString newtext, QString time,  QNChatMessage::User_Type type)
{
    text = text.trimmed();
    if(text==""){
        QMessageBox messageBox;
        messageBox.setIcon(QMessageBox::Warning);
        messageBox.setWindowTitle("警告");
        messageBox.setText("发送数据不能为空！");
        messageBox.setStandardButtons(QMessageBox::Ok);
        messageBox.exec();
        return;
    }
    newtext = newtext.trimmed();
    messageW->setFixedWidth(this->width());
    QSize size = messageW->fontRect(newtext,false);
    item->setSizeHint(size);

    messageW->setText(text, time, size, type,false);
    ui->listWidget->setItemWidget(item, messageW);
    ui->listWidget->scrollToBottom();
}
void client::dealimage(QNChatMessage *messageW, QListWidgetItem *item, QString filePath, QString time,  QNChatMessage::User_Type type)
{
    messageW->setFixedWidth(this->width());
    QImage image(filePath);
    QSize size = messageW->fontRect(filePath,true);
    item->setSizeHint(size);
    messageW->setText(filePath, time, size, type,true);
    ui->listWidget->setItemWidget(item, messageW);
    ui->listWidget->scrollToBottom();
}
void client::dealMessageTime(QString curMsgTime)
{
    bool isShowTime = false;
    if(ui->listWidget->count() > 0) {
        QListWidgetItem* lastItem = ui->listWidget->item(ui->listWidget->count() - 1);
        QNChatMessage* messageW = (QNChatMessage*)ui->listWidget->itemWidget(lastItem);
        int lastTime = messageW->time().toInt();
        int curTime = curMsgTime.toInt();
        isShowTime = ((curTime - lastTime) > 60); // 两个消息相差一分钟
    } else {
        isShowTime = true;
    }
    if(isShowTime) {
        QNChatMessage* messageTime = new QNChatMessage(ui->listWidget->parentWidget());
        QListWidgetItem* itemTime = new QListWidgetItem(ui->listWidget);
        QSize size = QSize(this->width(), 40);
        messageTime->resize(size);
        itemTime->setSizeHint(size);
        messageTime->setText(curMsgTime, curMsgTime, size, QNChatMessage::User_Time,false);
        ui->listWidget->setItemWidget(itemTime, messageTime);
    }
}
void client::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);
    for(int i = 0; i < ui->listWidget->count(); i++) {
        QNChatMessage* messageW = (QNChatMessage*)ui->listWidget->itemWidget(ui->listWidget->item(i));
        QListWidgetItem* item = ui->listWidget->item(i);
        dealMessage(messageW, item, messageW->text(),messageW->text(), messageW->time(), messageW->userType());
    }
}

/*Vido*/
void client::openVido(){
    QByteArray data=(QString(R"({
                             "Type":%1,
                             "User":"%2",
                             "Sender":"%3"
                             })").arg(SEND_TYPE).arg(ToUserName).arg(UserName)).toUtf8();
    QThread::msleep(10); //添加延时
    setVidoTcpSocket->write(data);
    //等待发送完成，才能继续下次发送，
    if(!setVidoTcpSocket->waitForBytesWritten(10*1000)) {
        qDebug()<<("网络请求超时");
        return;
    }

}
void client::closeVido(){
    ui->pushButton_4->setText("视频通话");
    if(capture->isOpened()){
        capture->release();
    }
    setVidoTcpSocket->write("Commopasd");
    vido->hide();
}
void client::VidoData(){
    ui->pushButton_4->setText("关闭");
    // 尝试打开默认摄像头（索引为0）
    if (!capture->open(0)) {
        qDebug() << "Error opening video capture";
        return;
    }
    vido->MEclear();
    vido->SHEclear();
    // 设置定时器以定期从摄像头捕获帧
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, [=](){
        if(ui->pushButton_4->text()=="视频通话")return;
        cv::Mat frame;
        *capture >> frame; // 从摄像头捕获帧
        QImage qtImage;
        if (!frame.empty()) {
            cvtColor(frame, frame, cv::COLOR_BGR2RGB); // 转换为RGB
            qtImage = QImage((const unsigned char*)(frame.data), frame.cols, frame.rows, frame.step, QImage::Format_RGB888);
            qtImage = QImage(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888).rgbSwapped();
        }
        QPixmap pixmap = QPixmap::fromImage(qtImage.rgbSwapped());
        vido->setMEPixmap(pixmap);// OpenCV使用BGR，而Qt使用RGB
        //将QPixmap转换为字节数组
        QBuffer buffer;
        buffer.open(QIODevice::WriteOnly);
        qtImage.save(&buffer, "JPEG");

        // 发送QPixmap数据到服务端
        setVidoTcpSocket->write(buffer.data(), buffer.size());
        if(!setVidoTcpSocket->waitForBytesWritten(10*2)) {
            qDebug()<<("网络请求超时");
            return;
        }
    });
    vido->show();
    timer->start(30); // 每30毫秒捕获一次帧
}

void client::on_pushButton_released()
{
    QString messages = ui->textEdit->toPlainText();
    QString time = QString::number(QDateTime::currentDateTime().toTime_t()); //时间戳
    QNChatMessage* messageW = new QNChatMessage(ui->listWidget->parentWidget());
    QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
    dealMessage(messageW, item, messages,messages , time, QNChatMessage::User_Me);
    messageW->setTextSuccess();
    ui->textEdit->setText("");
    QByteArray data=(QString(R"({
                             "Type":%1,
                             "User":"%2",
                             "Sender":"%3",
                             "Messages":"%4"
                             })").arg(SEND_TYPE).arg(ToUserName).arg(UserName).arg(messages)).toUtf8();
    MessagesTcpSocket->write(data);
}
void client::on_pushButton_2_clicked()
{
    ServerFilePath = QFileDialog::getOpenFileName(this, "选择文件", "/");
    if(ServerFilePath=="") return;
    QString time = QString::number(QDateTime::currentDateTime().toTime_t()); //时间戳
    QNChatMessage* messageW = new QNChatMessage(ui->listWidget->parentWidget());
    QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
    if(ServerFilePath.endsWith(".jpg")
     ||ServerFilePath.endsWith(".png")
     ||ServerFilePath.endsWith(".gif"))is_images=true;
    else is_images=false;
    if(is_images)dealimage(messageW, item, ServerFilePath, time, QNChatMessage::User_Me);
    QFile file(ServerFilePath);
    QString msg;
    if(file.size()>1024*1024) {
        toServerFileSize = QString("%1M").arg(file.size()/1024/1024.0);
    }
    else {
        toServerFileSize = QString("%1KB").arg(file.size()/1024.0);
    }

    toServerFileViewList[ToUserName].push_back({messageW,ServerFilePath});
    toServerFileViewList[ToUserName].back().first->fileSize=toServerFileSize;
    auto i = toServerFileViewList[ToUserName].back();

    connect(i.first,&QNChatMessage::released,[=](){
        if(!i.second.endsWith(".jpg")
         &&!i.second.endsWith(".png")
         &&!i.second.endsWith(".gif")){
            if(!i.second.endsWith(".zip")
             &&!i.second.endsWith(".rar")
             &&!i.second.endsWith(".tar.gz")){
                // 读取文件内容
                QFile file(i.second);
                file.open(QIODevice::ReadOnly | QIODevice::Text);
                QTextStream in(&file);
                QString fileContent = in.readAll();
                QTextEdit *textEdit = new QTextEdit();
                textEdit->setText(fileContent);
                textEdit->resize(600,600);
                textEdit->setWindowTitle(i.second.right(i.second.size()-i.second.lastIndexOf('/')-1));
                textEdit->show();
            }else{
                QString path = QCoreApplication::applicationDirPath()+"/../下载";
                QDesktopServices::openUrl(QUrl("file:"+path, QUrl::TolerantMode));
            }
        }
    });
    is_images=true;
    dealimage(toServerFileViewList[ToUserName].back().first, item, ServerFilePath, time, QNChatMessage::User_Me);
//    toServerFileViewList[ToUserName].back().first->setTextSuccess();
    is_images=false;
    emit sendMessage(ServerFilePath);
}
void client::on_pushButton_3_released()
{
    ServerIp = ui->lineEdit_2->text();
    UserName=ui->lineEdit_3->text();
    ToUserName=ui->lineEdit->text();
    setWindowTitle(UserName);
    ui->listWidget->clear();
    fileThread = new FileThread(ServerIp,UserName,ToUserName);
    connect(fileThread,&FileThread::FilePath,this,[&](QString filePath,QString getServerFileSize){
        QString time = QString::number(QDateTime::currentDateTime().toTime_t()); //时间戳
        QNChatMessage* messageW = new QNChatMessage(ui->listWidget->parentWidget());
        QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
        if(filePath.endsWith(".jpg")
         ||filePath.endsWith(".png")
         ||filePath.endsWith(".gif"))is_images=true;
        else is_images=false;
        if(is_images)dealimage(messageW, item, filePath, time, QNChatMessage::User_She);
        messageW->setTextSuccess();
        getServerFileViewList[ToUserName].push_back({new QNChatMessage(ui->listWidget->parentWidget()),filePath});
        getServerFileViewList[ToUserName].back().first->fileSize=getServerFileSize;
        auto i = getServerFileViewList[ToUserName].back();
        connect(i.first,&QNChatMessage::released,[=](){
            if(!i.second.endsWith(".jpg")
             &&!i.second.endsWith(".png")
             &&!i.second.endsWith(".gif")){
                if(!i.second.endsWith(".zip")
                 &&!i.second.endsWith(".rar")
                 &&!i.second.endsWith(".tar.gz")){
                    // 读取文件内容
                    QFile file(i.second);
                    file.open(QIODevice::ReadOnly | QIODevice::Text);
                    QTextStream in(&file);
                    QString fileContent = in.readAll();
                    QTextEdit *textEdit = new QTextEdit();
                    textEdit->setText(fileContent);
                    textEdit->resize(600,600);
                    textEdit->setWindowTitle(i.second.right(i.second.size()-i.second.lastIndexOf('/')-1));
                    textEdit->show();
                }else{
                    QString path = QCoreApplication::applicationDirPath()+"/../下载";
                    QDesktopServices::openUrl(QUrl("file:"+path, QUrl::TolerantMode));
                }
            }
        });
        is_images=true;
        dealimage(getServerFileViewList[ToUserName].back().first, item, filePath, time, QNChatMessage::User_She);
        getServerFileViewList[ToUserName].back().first->setTextSuccess();
        is_images=false;
    });
    connect(fileThread,&FileThread::receive,this,[&](){//更改文件发送状态
        toServerFileViewList[ToUserName].back().first->setTextSuccess();
    });
    // 主线程向子线程发送消息
    connect(this, &client::sendMessage, fileThread, &FileThread::getPath);
    fileThread->start();
    MessagesSockerInit();
    setVidoInit();
    getVidoInit();
}
void client::on_pushButton_4_released()
{
    if(ui->pushButton_4->text()=="视频通话")openVido();
    else closeVido();
}
void client::on_pushButton_6_released()
{
    MyEmijo->show();
    connect(MyEmijo,&Emijo::getEmijo,this,[=](QString emijo){
        // 获取光标位置
        QTextCursor cursor = ui->textEdit->textCursor();
        // 将光标移动到文本末尾
        cursor.movePosition(QTextCursor::End);
        // 在光标位置插入新内容
        cursor.insertText(emijo);
        // 重新设置光标位置
        ui->textEdit->setTextCursor(cursor);
        MyEmijo->hide();
        disconnect(MyEmijo,&Emijo::getEmijo,this,nullptr);
    });
}
void client::on_pushButton_7_released()
{
    QString messages = ui->textEdit->toPlainText();
    ui->textEdit->setText("");
    if(messages=="")return;
    QString time = QString::number(QDateTime::currentDateTime().toTime_t()); //时间戳
    QNChatMessage* messageW = new QNChatMessage(ui->listWidget->parentWidget());
    QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
    dealMessage(messageW, item, messages,messages , time, QNChatMessage::User_Me);
    messageW->setTextSuccess();
    ui->pushButton_7->setStyleSheet("background-color: rgb(237, 51, 59);");
    chatbot->sendMessage(messages);
    ui->pushButton_7->setEnabled(false);
}
